package cn.bjxy.shishaolong.talk_room.server;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.JComboBox;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.DefaultTableModel;

import cn.bjxy.shishaolong.talk_room.server.entity.IpAndPort;
import cn.bjxy.shishaolong.talk_room.server.entity.Message;
import cn.bjxy.shishaolong.talk_room.server.entity.User;

/**
 * 聊天室，服务器端服务 
 * @author long
 *
 */
class ServerService {   //设置了包访问权限，只有同包才能访问

	// 服务端socket引用。
	private DatagramSocket ds;
	// 判断服务端服务是否关闭标识
	private boolean isClosed = false;
	// 定义一个set集合来存储当前聊天用户
	private static Set<User> users = new HashSet<User>();
	// 历史聊天记录
	private static List<Message> messages = new ArrayList<Message>();

	
	Set<User> getUsers() {
		return users;
	}
//	private static void addUsers(User user) {
//		users.add(user);
//	}
	List<Message> getMessages() {
		return messages;
	}
//	private static void addMessage(Message message) {
//		messages.add(message);
//	}
	boolean isClosed() {
		return isClosed;
	}

	/**
	 * 负责处理客户端消息的任务
	 * @author long
	 *
	 */
	class HandlellerService implements Runnable {
		
		private JTextArea showInfo_tArea;
		private JTable member_jTable;
		private StringBuilder receivedMessage = new StringBuilder();
		
		public HandlellerService(int port, JTextArea showInfo_tArea,JTable member_jTable) {
			try {
				this.showInfo_tArea = showInfo_tArea;
				this.member_jTable = member_jTable;
				ds = new DatagramSocket(port);
			} catch (SocketException e) {
				e.printStackTrace();
			}
		}

		public void run() {
			while (!isClosed) {
				try {
					// 2. 创建数据包。
					byte[] buf = new byte[1024];
					DatagramPacket dp = new DatagramPacket(buf, buf.length);

					// 3. 使用接收方法将数据存储到数据包中。
					ds.receive(dp);

					// 4. 通过数据包对象的方法，解析其中的数据，比如：地址，端口，数据内容。
					String ip = dp.getAddress().getHostAddress();
					int port = dp.getPort();
					String content = new String(dp.getData(), 0, dp.getLength());

					User user = null;
					IpAndPort ipAndPort = new IpAndPort(ip, port);
					if ((user = getUserByIpAndPort(ipAndPort)) == null) {
						user = new User();
						user.setName("用户" + (users.size() + 1));
						user.setIpAndPort(ipAndPort);
						users.add(user);
						addUserToUI();
					}

					// 封装消息，将消息保存到消息集当中
					Message message = new Message();
					message.setDate(new Date());
					message.setContent(content);
					message.setUser(user);
					messages.add(message);
					showInfo_tArea.append(message.toString());;
					
					// 将聊天内容转发给所有的客户端
					sendMessage(message.toString());
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} // 阻塞式的。
			}
		}
		
		//更新界面的用户信息表格
		private void addUserToUI() {
			User[] usersArray = users.toArray(new User[users.size()]);
			String[] header = {"用户列表"};
			String[][] data = new String[usersArray.length][1];
			for(int i=0; i<usersArray.length;i++) {
				data[i][0] = usersArray[i].toString();
			}
			member_jTable.setModel(new DefaultTableModel(data,header));
		}

		/**
		 * 向所有用户转发消息
		 * @param message 要转发的消息 
		 */
		private void sendMessage(String message) {
			byte[] buf = message.getBytes();
			for (User user : users) {
				IpAndPort ipAndPort = user.getIpAndPort();
				try {
					DatagramPacket packet = 
							new DatagramPacket(buf, buf.length, InetAddress.getByName(ipAndPort.getIp()), ipAndPort.getPort());
					ds.send(packet);
				} catch (UnknownHostException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 关闭处理聊天服务
	 */
	public void closeService() {
		isClosed = true;
		ds.close();
	}
	
	/**
	 * 关闭服务任务
	 * @author long
	 *
	 */
/*	class closeService implements Runnable{

		public void run() {
			isClosed = true;
			ds.close();
		}
	}*/
	
	/*
	 * 判断是否有这个ip(即用户)
	 */
	private User getUserByIpAndPort(IpAndPort ipAndPort) {
		for (User user : users) {
			if(ipAndPort.equals(user.getIpAndPort()))
				return user;
		}
		return null;
	}
}
